minetest.register_tool('tasks:configurator', {
   description = 'Configurator Wrench',
   inventory_image = 'tasks_wrench.png',
   on_use = function(itemstack, user, pointed_thing)
      local pos = minetest.get_pointed_thing_position(pointed_thing)
      if pos then
         local name = user:get_player_name()
         local node = minetest.get_node(pos)
         if not minetest.is_protected(pos, name) or minetest.check_player_privs(name, {server = true}) then
            tasks.player_config[name] = pos
            if minetest.get_item_group(node.name, 'tasks') > 0 then
               tasks.configure(pos, name)
            elseif minetest.get_item_group(node.name, 'door') > 0 then
               doors.lock(pos, name)
            elseif minetest.get_item_group(node.name, 'stash') > 0 then
               tasks.stash(pos, name)
            elseif minetest.get_item_group(node.name, 'sabotage') > 0 then
               sabotage.on_rightclick(pos, node, user)
            end
         end
      end
   end,
   on_drop = lobby.no_drop
})

function tasks.configure(pos, name)
   local meta = minetest.get_meta(pos)
   local info_working = meta:get_string('info_working')
   local info_repair = meta:get_string('info_repair')
   local time_min = meta:get_int('time_min') or 60
   local time_max = meta:get_int('time_max') or 120
   local xp = meta:get_int('xp') or 5
   local level = meta:get_int('level') or 0
   if info_working == '' then
      info_working = meta:get_string('infotext')
   end
   minetest.show_formspec(name, 'tasks:configuration', tasks.configuration_formspec(info_working, info_repair, time_min, time_max, xp, level))
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
   local name = player:get_player_name()
   if formname == 'tasks:configuration' then
      if fields.save then
         if tasks.is_integer(fields.time_min) and tasks.is_integer(fields.time_max) and tasks.is_integer(fields.xp)
            and tonumber(fields.time_max) >= tonumber(fields.time_min) and tasks.is_integer(fields.level) then
               local pos = tasks.player_config[name]
               local meta = minetest.get_meta(pos)
               local timer = minetest.get_node_timer(pos)
               meta:set_int('time_min', math.max(fields.time_min,5))
               meta:set_int('time_max', math.max(fields.time_max,20))
               meta:set_int('xp', math.max(fields.xp,0))
               meta:set_int('level', math.min(fields.level, 4))
               meta:set_string('info_working', fields.info_working)
               meta:set_string('info_repair', fields.info_repair)
               local random_number = math.random(fields.time_min, fields.time_max)
               timer:start(random_number)
         else
            minetest.chat_send_player(name, 'Please check your inputs.')
         end
      end
   end
end)

function tasks.configuration_formspec(info_working, info_repair, time_min, time_max, xp, level)
   local formspec =
      'formspec_version[3]'..
      'size[12,10]'..
      'background[-2,-2;16,14;tasks_configurator_ui_bg.png]'..
      'textarea[0,0;12,3.5;;;Set the time range a task can become available within. '..
      'A random number within the range will be used. Minimum time must be 5 or more seconds, '..
      'and max time must be 20 or more seconds. Whole numbers only! '..
      'Right-clicking on an unavailable task will restart the timer with a new random number. '..
      'If you always want the task to take the same length of time to become available simply set both values to the same number.\n'..
      'Enter the amount of XP to be granted to a player in a match. Ghosts will add half this value, '..
      'and players solo playing a level will only get 1 XP.\n'..
      'Levels can be 1-4, if the level is below the sabotage level it can be interacted with while the map is sabotaged.\n'..
      'Do note that not all tasks have configurable infotexts even though they display here.]'..
      'field[0,4.5;12,.6;info_working;Infotext to displayed when the task is unavailable;'..info_working..']'..
      'field[0,5.75;12,.6;info_repair;Infotext to displayed when the task is available;'..info_repair..']'..
      'field[0,7;2,.6;time_min;Min time;'..time_min..']'..
      'field[3.25,7;2,.6;time_max;Max time;'..time_max..']'..
      'field[6.75,7;2,.6;xp;XP;'..xp..']'..
      'field[10,7;2,.6;level;Level;'..level..']'..
      'button_exit[8,9;3,1;save;Submit]'
   return formspec
end

function tasks.stash(pos, name)
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   inv:set_size('stash', 8)
   local infotext = meta:get_string('infotext')
   minetest.show_formspec(name, 'tasks:stash', tasks.stash_formspec(pos, infotext))
end

function tasks.stash_formspec(pos, infotext)
   local spos = pos.x ..','.. pos.y ..','.. pos.z
   local formspec =
      'formspec_version[3]'..
      'size[10.25,7.5]'..
      'listcolors[#00000069;#5a5a5a]'..
      'textarea[.5,1.5;9.75,2;;;Place items above to let people find them in this node. If their search is successful they will randomly get one of the items here. Blanks will give nothing.]'..
      'field[1,3.0;5,.5;infotext;Infotext;'..infotext..']'..
      'list[detached:creative_trash;main;9,2.5;1,1;]'..
      'image[9,2.5;1,1;creative_trash_icon.png]'..
      'list[nodemeta:'..spos..';stash;.25,.25;8,1;]'..
      'list[detached:tasks_stash;main;.25,4.0;8,2;]'..
      'listring[]'..
      'button_exit[4,6.5;2.25,.75;save;Submit]'
   return formspec
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
   local name = player:get_player_name()
   if formname == 'tasks:stash' then
      if fields.save then
         local pos = tasks.player_config[name]
         local meta = minetest.get_meta(pos)
         meta:set_string('infotext', fields.infotext)
      end
   end
end)

minetest.create_detached_inventory('tasks_stash', {
   allow_put = function(inv, listname, index, stack, player2)
      return 0
   end,
   allow_take = function(inv, listname, index, stack, player2)
      local name = player2 and player2:get_player_name() or ''
      if not creative.is_enabled_for(name) then
         return 0
      end
      return -1
   end,
   on_move = function(inv, from_list, from_index, to_list, to_index, count, player2)
   end,
})

local stashable = {}
minetest.register_on_mods_loaded(function()
   for name, def in pairs(minetest.registered_items) do
      local group = def.groups or {}
      if group.stashable then
         stashable[name] = def
      end
   end
   local list = {}
   for name, def in pairs(stashable) do
      list[#list+1] = name
   end
   local stash_inv = minetest.get_inventory({type = 'detached', name = 'tasks_stash'})
   stash_inv:set_size('main', #list)
   stash_inv:set_list('main', list)
end)
